<?php

namespace app\api\controller;

use app\api\model\Mobile as MobileModel;
use app\common\model\Alipay;
use app\common\model\Wxpay;
use EasyWeChat\Factory;
use think\facade\Db;
use think\facade\Log;

/**
 * 这边的入口，关闭【v1.0】
 */
class Mobile extends \app\BaseController
{
    private $settle_discount_slow = 100;  // 【慢充】结算折扣：代理商与平台的折扣
    private $settle_discount_slow_all = [100, 100, 100, 100];  // 【慢充】结算折扣：代理商与平台的折扣，区分运营商
    private $sale_discount_slow = 100;    // 【慢充】销售折扣：代理商给用户的折扣 $settle_discount_slow < $sale_discount_slow
    private $settle_discount_fast = 100;  // 【快充】结算折扣：代理商与平台的折扣
    private $settle_discount_fast_all = [100, 100, 100, 100];  // 【快充】结算折扣：代理商与平台的折扣，区分运营商
    private $sale_discount_fast = 100;    // 【快充】销售折扣：代理商给用户的折扣 $settle_discount_fast < $sale_discount_fast
    private $slow_status = 1;
    private $fast_status = 1;
    private $redirect_uri = '';
    private $agentChannel = null;
    private $config = null;
    private $settleType = SETTLE_TYPE_PROFIT;   // 结算类型：1返佣 2预充
    private $wxpayAgentId = 0;
    private $error = '';

    protected function initialize()
    {
        $channel = input('channel');
        $this->redirect_uri = env('app.agent_url') . '/h5?channel=' . $channel;
        $agentChannel = Db::name('agent_channel')
            ->where('name', $channel)
            ->where('is_deleted', 0)
            ->find();
        $this->agentChannel = $agentChannel;

        if (!empty($agentChannel)) {
            $this->slow_status = $agentChannel['mobile_status_slow'];
            $this->fast_status = $agentChannel['mobile_status_fast'];

            // 渠道的销售价【慢充】
            $this->sale_discount_slow = $agentChannel['mobile_discount_slow'];
            if ($this->sale_discount_slow > 100 || $this->sale_discount_slow < 90) {
                $this->sale_discount_slow = 96;
            }
            // 渠道的销售价【快充】
            $this->sale_discount_fast = $agentChannel['mobile_discount_fast'];
            if ($this->sale_discount_fast > 100 || $this->sale_discount_fast < 90) {
                $this->sale_discount_fast = 99;
            }

            // 代理商的结算价
            $agent = Db::name('agent')
                ->field('settle_type, mobile_discount_slow, mobile_discount_fast')
                ->where('id', $agentChannel['agent_id'])
                // ->where('status', 1)
                ->find();
            $config = Db::name('agent_service_config')
                ->field('discount_slow, discount_fast, discount_slow_all, discount_fast_all')
                ->where('agent_id', $agentChannel['agent_id'])
                ->where('serv_type', PRODUCT_MOBILE_SERV)
                ->find();
            $this->settleType = $agent['settle_type'] ?? SETTLE_TYPE_PROFIT;
            $this->settle_discount_slow = $config['discount_slow'];
            $this->settle_discount_slow_all = json_decode($config['discount_slow_all'], true);
            $this->settle_discount_fast = $config['discount_slow'];
            $this->settle_discount_fast_all = json_decode($config['discount_fast_all'], true);
            // $this->settle_discount_slow = $agent['mobile_discount_slow'] ?? 100;
            // if ($this->settle_discount_slow > 100 || $this->settle_discount_slow < 90) {
            //     $this->settle_discount_slow = 100;
            // }
            // $this->settle_discount_fast = $agent['mobile_discount_fast'] ?? 100;
            // if ($this->settle_discount_fast > 100 || $this->settle_discount_fast < 90) {
            //     $this->settle_discount_fast = 100;
            // }
        }

        // 销售价不能低于结算价[废弃，代理商可以亏本卖]
        // if ($this->settle_discount_slow > $this->sale_discount_slow) {
        //     $this->sale_discount_slow = $this->settle_discount_slow;
        // }
        // if ($this->settle_discount_fast > $this->sale_discount_fast) {
        //     $this->sale_discount_fast = $this->settle_discount_fast;
        // }

        if ($this->settleType == SETTLE_TYPE_PROFIT) {
            // 返佣，使用公司的支付账号
            $this->config = Db::name('config')
                ->where('type', 'wechat')
                ->column('value', 'field');
        } else {
            // 预充，使用客户的支付账号
            $this->config = Db::name('agent_config')
                ->where('agent_id', $agentChannel['agent_id'])
                ->find();
            $this->wxpayAgentId = $agentChannel['agent_id'];
        }
    }

    public function getSetting()
    {
        $token = $this->request->header('Authorization');
        if (!empty($token)) {
            Db::name('mobile_user')
                ->where('token', $token)
                ->update([
                    'expired_at' => time() + 7200,
                ]);
        }

        $filename = root_path() . '/data/mobileSupplierPriority.json';
        $data = file_get_contents($filename);
        $data = json_decode($data, true) ?? [];

        $tabList = [];
        if ($this->slow_status == 1) {
            $this->sale_discount_slow = floatval($this->sale_discount_slow);
            $tabList[] = [
                'name' => $this->sale_discount_slow . '折慢充',
                'isFast' => 0,
                'discount' => $this->sale_discount_slow,
                'amountList' => [
                    // 30 => empty($data['other_slow'][30]) ? 0 : 1,
                    50 => empty($data['other_slow'][50]) ? 0 : 1,
                    100 => empty($data['other_slow'][100]) ? 0 : 1,
                    200 => empty($data['other_slow'][200]) ? 0 : 1,
                ],
            ];
        }
        if ($this->fast_status == 1) {
            $this->sale_discount_fast = floatval($this->sale_discount_fast);
            $tabList[] = [
                'name' => $this->sale_discount_fast . '折快充',
                'isFast' => 1,
                'discount' => $this->sale_discount_fast,
                'amountList' => [
                    // 30 => empty($data['other_fast'][30]) ? 0 : 1,
                    50 => empty($data['other_fast'][50]) ? 0 : 1,
                    100 => empty($data['other_fast'][100]) ? 0 : 1,
                    200 => empty($data['other_fast'][200]) ? 0 : 1,
                ],
            ];
        }

        $amountConfig = [];
        $fields = [
            'yidong_fast', 'liantong_fast', 'dianxin_fast', 'other_fast',
            'yidong_slow', 'liantong_slow', 'dianxin_slow', 'other_slow',
        ];
        foreach ($fields as $field) {
            // $amountConfig[$field][30] = empty($data[$field][30]) ? 0 : 1;
            $amountConfig[$field][50] = empty($data[$field][50]) ? 0 : 1;
            $amountConfig[$field][100] = empty($data[$field][100]) ? 0 : 1;
            $amountConfig[$field][200] = empty($data[$field][200]) ? 0 : 1;
        }

        return success('获取成功', [
            'appid' => $this->config['app_id'] ?? '',
            'redirect_uri' => $this->redirect_uri,
            'discount_slow' => $this->sale_discount_slow,
            'discount_fast' => $this->sale_discount_fast,
            'list' => MobileModel::getAmountList(),
            'tabList' => $tabList,
            'isDeleted' => $this->agentChannel['is_deleted'] ?? 1,
            'amountConfig' => $amountConfig,
            'agent_id' => $this->agentChannel['agent_id'] ?? 0,
        ]);
    }

    /**
     * 创建订单
     * 微信 H5 支付.
     */
    public function h5Pay()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $params = $this->formatOrderParams();
        if (false === $params) {
            return fail($this->error);
        }
        $params['trade_type'] = 'MWEB';
        $params['pay_channel'] = PAY_WEIXIN;
        $model = new MobileModel();
        $res = $model->create($params);
        if (false === $res) {
            return fail($model->getError());
        }
        $payLog = $res['payLog'];
        $orderId = $res['orderId'];
        unset($res);

        try {
            $pay = new Wxpay($this->wxpayAgentId, 'wechat_mweb');
            $res = $pay->create([
                'body' => '话费充值 ' . fen2yuan($payLog['amount']) . ' 元',
                'out_trade_no' => $orderId,
                'total_fee' => $payLog['sale_price'],
                'spbill_create_ip' => $this->request->ip(),
                'trade_type' => $payLog['trade_type'],
            ]);
            if (!isset($res['return_code']) || $res['return_code'] != 'SUCCESS') {
                Log::write($res, 'error');
                return fail($res['return_msg'] ?? '支付订单生成失败，请稍后再试。');
            }
            if (!isset($res['result_code']) || $res['result_code'] != 'SUCCESS') {
                Log::write($res, 'error');
                return fail($res['err_code_des'] ?? '支付订单生成失败，请稍后再试！');
            }
            if (!empty($res['mweb_url'])) {
                $res['mweb_url'] .= '&redirect_url=' . urlencode($this->redirect_uri);
            }
            $res['orderId'] = $orderId;

            return success('下单成功', $res);
        } catch (\Exception $e) {
            return fail('微信 H5 支付配置有误，请确认');
        }
    }

    /**
     * JSAPI 支付.
     */
    public function jsapiPay()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $token = $this->request->header('Authorization');
        if (empty($token)) {
            return fail('请先登录', 401);
        }
        $user = Db::name('mobile_user')
            ->where('token', $token)
            ->find();
        if (empty($user) || $user['expired_at'] < time()) {
            return fail('登录已过期', 401);
        }

        $params = $this->formatOrderParams();
        if (false === $params) {
            return fail($this->error);
        }
        $params['trade_type'] = 'JSAPI';
        $params['user_id'] = $user['id'];
        $params['pay_channel'] = PAY_WEIXIN;
        $model = new MobileModel();
        $res = $model->create($params);
        if (false === $res) {
            return fail($model->getError());
        }
        $payLog = $res['payLog'];
        $orderId = $res['orderId'];
        unset($res);

        try {
            $pay = new Wxpay($this->wxpayAgentId);
            $res = $pay->create([
                'body' => '话费充值 ' . fen2yuan($payLog['amount']) . ' 元',
                'out_trade_no' => $orderId,
                'total_fee' => $payLog['sale_price'],
                'spbill_create_ip' => $this->request->ip(),
                'trade_type' => $payLog['trade_type'],
                'openid' => $user['openid'],
            ]);
            if (!isset($res['return_code']) || $res['return_code'] != 'SUCCESS') {
                Log::write($res, 'error');
                return fail($res['return_msg'] ?? '支付订单生成失败，请稍后再试。');
            }
            if (!isset($res['result_code']) || $res['result_code'] != 'SUCCESS') {
                Log::write($res, 'error');
                return fail($res['err_code_des'] ?? '支付订单生成失败，请稍后再试！');
            }
            $payment = $pay->jssdk($res['prepay_id']);
            $payment['orderId'] = $orderId;

            return success('下单成功', $payment);
        } catch (\Exception $e) {
            return fail('微信公众号支付配置有误，请确认' . $e->getMessage());
        }
    }

    /**
     * 支付宝支付.
     */
    public function alipay()
    {
        return fail('该支付方式暂时不支持');    // 支付宝交易退款的话，手续费不退，所以关闭

        $params = $this->formatOrderParams();
        if (false === $params) {
            return fail($this->error);
        }
        $params['trade_type'] = 'ALIPAY';
        $params['pay_channel'] = PAY_ALIPAY;
        $model = new MobileModel();
        $res = $model->create($params);
        if (false === $res) {
            return fail($model->getError());
        }
        $payLog = $res['payLog'];
        $orderId = $res['orderId'];
        unset($res);

        try {
            $pay = new Alipay($this->wxpayAgentId);

            return $pay->wap([
                'name' => '话费充值 ' . fen2yuan($payLog['amount']) . ' 元',
                'out_trade_no' => $orderId,
                'total_amount' => $payLog['sale_price'],
                'channel' => input('channel'),
            ]);
        } catch (\Exception $e) {
            return fail('支付宝支付配置有误，请确认');
        }
    }

    private function formatOrderParams()
    {
        $params = input('post.');
        $params['settle_type'] = $this->settleType;
        $ispType = getMobileIsp($params['mobile']); // 1移动 2联通 3电信 -1其他
        if (!empty($params['is_fast'])) {
            // 快充
            $params['sale_discount'] = $this->sale_discount_fast;
            // 结算价格区分运营商
            $params['settle_discount'] = $this->settle_discount_fast_all[$ispType] ?? $this->settle_discount_fast;
            $orderType = 2;
        } else {
            // 慢充
            $params['sale_discount'] = $this->sale_discount_slow;
            // 结算价格区分运营商
            $params['settle_discount'] = $this->settle_discount_slow_all[$ispType] ?? $this->settle_discount_slow;
            $orderType = 1;
        }

        // 筛选话费供应商 -- start
        // 指定的供应商
        $agentId = $this->agentChannel['agent_id'] ?? 0;
        $usedSupplierIds = Db::name('agent_mobile_supplier')
            ->where('agent_id', $agentId)
            ->column('mobile_supplier_id');

        // 代理商是否被禁用
        $agentStatus = Db::name('agent')
            ->where('id', $agentId)
            ->value('status');
        if ($agentStatus != 1) {
            $this->error = '通道已禁用';

            return false;
        }

        $map = [
            1 => 'yidong',
            2 => 'liantong',
            3 => 'dianxin',
            -1 => 'other',
        ];
        // $ispType = getMobileIsp($params['mobile']);
        $fieldName = $map[$ispType];
        if ($orderType == 1) {
            $fieldName .= '_slow';
        } else {
            $fieldName .= '_fast';
        }
        $filename = root_path() . '/data/mobileSupplierPriority.json';
        $priority = file_get_contents($filename);
        $priority = json_decode($priority, true);
        if (empty($priority) || empty($priority[$fieldName][$params['amount']])) {
            $this->error = '充值面额维护中';

            return false;
        }
        $tmp = $priority[$fieldName][$params['amount']];
        // todo 待优化
        $supplier = [];
        foreach ($tmp as $id => $num) {
            if (!in_array($id, $usedSupplierIds)) {
                continue;
            }
            $supplier = array_merge($supplier, array_fill(0, $num, $id));
        }
        if (empty($supplier)) {
            $this->error = '充值通道维护中';

            return false;
        }
        $max = count($supplier) - 1;
        $index = random_int(0, $max);
        $mobileSupplierId = $supplier[$index];
        unset($supplier);
        unset($priority);
        // 筛选话费供应商 -- end

        $params['agent_id'] = $this->agentChannel['agent_id'] ?? 0;
        $params['channel_id'] = $this->agentChannel['id'] ?? 0;
        $params['mobile_supplier_id'] = $mobileSupplierId;

        return $params;
    }

    /**
     * 订单取消支付.
     */
    public function cancel()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $orderId = input('post.orderId');
        $payLog = Db::name('pay_log')
            ->field('id, status')
            ->where('order_id', $orderId)
            ->find();
        if (empty($payLog) || $payLog['status'] == 3) {
            return success('取消成功');
        }

        if ($payLog['status'] == 2) {
            return fail('订单已经支付，无法取消');
        }

        Db::startTrans();
        try {
            Db::name('pay_log')
                ->where('id', $payLog['id'])
                ->update([
                    'status' => 3,
                    'remark' => '支付取消',
                ]);
            Db::name('mobile_order')
                ->where('order_id', $payLog['order_id'])
                ->update([
                    'status' => '3',
                    'remark' => '支付取消',
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            return fail('取消失败：' . $e->getMessage());
        }

        return success('取消成功');
    }

    /**
     * 根据 code 获取用户 openid.
     */
    public function loginFromCode()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $token = $this->request->header('Authorization');
        if (!empty($token)) {
            $user = Db::name('mobile_user')
                ->where('token', $token)
                ->find();
            $now = time();
            if (!empty($user) && $user['expired_at'] >= $now) {
                Db::name('mobile_user')
                    ->where('id', $user['id'])
                    ->update([
                        'expired_at' => $now + 7200,
                    ]);

                return success('已登录', [
                    'token' => $token,
                ]);
            }
        }

        $app = Factory::officialAccount([
            'app_id' => $this->config['app_id'],
            'secret' => $this->config['app_secret'],

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',
        ]);
        try {
            $user = $app->oauth->user();
            $openid = $user->id;
            $token = $this->generateToken();
            if (false === $token) {
                return fail('token 生成失败，请刷新重试');
            }
            $id = Db::name('mobile_user')
                ->where('app_id', $this->config['app_id'])
                ->where('openid', $openid)
                ->value('id');
            $now = time();
            if ($id) {
                Db::name('mobile_user')
                    ->where('id', $id)
                    ->update([
                        'token' => $token,
                        'expired_at' => $now + 7200,
                    ]);
            } else {
                Db::name('mobile_user')->insert([
                    'agent_id' => $this->agentChannel['agent_id'] ?? 0,
                    'app_id' => $this->config['app_id'],
                    'openid' => $openid,
                    'token' => $token,
                    'expired_at' => $now + 7200,
                ]);
            }
        } catch (\Exception $e) {
            return fail('登录失败，请刷新重试:' . $e->getMessage());
        }

        return success('登录成功', [
            'token' => $token,
        ]);
    }

    /**
     * 根据合作伙伴id获取用户token.
     */
    public function loginFromPartnerId()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $agentId = $this->agentChannel['agent_id'] ?? 0;
        $partnerId = input('post.partnerId');
        if (empty($agentId) || empty($partnerId)) {
            return fail('参数缺失489');
        }

        try {
            $token = $this->generateToken();
            if (false === $token) {
                return fail('token 生成失败，请刷新重试');
            }
            $id = Db::name('mobile_user')
                ->where('app_id', $this->config['app_id'])
                ->where('openid', $partnerId)
                ->where('agent_id', $agentId)
                ->value('id');
            $now = time();
            if ($id) {
                Db::name('mobile_user')
                    ->where('id', $id)
                    ->update([
                        'token' => $token,
                        'expired_at' => $now + 7200,
                    ]);
            } else {
                Db::name('mobile_user')->insert([
                    'agent_id' => $agentId,
                    'app_id' => $this->config['app_id'],
                    'openid' => $partnerId,
                    'token' => $token,
                    'expired_at' => $now + 7200,
                ]);
            }
        } catch (\Exception $e) {
            return fail('登录失败，请刷新重试:' . $e->getMessage());
        }

        return success('登录成功', [
            'token' => $token,
        ]);
    }

    /**
     * jssdk.
     */
    public function jssdk()
    {
        $app = Factory::officialAccount([
            'app_id' => $this->config['app_id'],
            'secret' => $this->config['app_secret'],

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',
        ]);
        $url = input('post.url');
        $res = $app->jssdk->setUrl($url)->buildConfig(['updateAppMessageShareData', 'updateTimelineShareData'], false, false, false, ['wx-open-launch-weapp']);

        return success('操作成功', $res);
    }

    public function generateToken()
    {
        for ($i = 0; $i < 21; ++$i) {
            $token = md5(microtime(true) . session_create_id());
            $id = Db::name('mobile_user')
                ->where('token', $token)
                ->value('id');
            if (empty($id)) {
                return $token;
            }
        }

        return false;
    }

    public function checkLogin()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $token = $this->request->header('Authorization');
        $appid = $this->config['app_id'] ?? '';
        if (empty($token)) {
            return fail('未登录' . $appid);
        }
        $user = Db::name('mobile_user')
            ->where('token', $token)
            ->where('app_id', $appid)
            ->find();
        $now = time();
        if (empty($user) || $user['expired_at'] < $now) {
            return fail('登录过期');
        }
        Db::name('mobile_user')
            ->where('token', $token)
            ->update([
                'expired_at' => $now + 7200,
            ]);

        return success('已登录', [
            'token' => $token,
        ]);
    }

    public function orderList()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $token = $this->request->header('Authorization');
        $where = [];
        $where[] = ['status', '=', 2];
        $where[] = ['order_type', '=', input('order_type', 1)];
        $userId = 0;
        if (!empty($token)) {
            $user = Db::name('mobile_user')
                ->where('token', $token)
                ->find();
            $now = time();
            if (empty($user) || $user['expired_at'] < $now) {
                return success('操作成功', []);
            }

            $userId = $user['id'];
        }

        $orderIds = input('orderIds');

        if (!empty($orderIds) && $userId) {
            Db::name('mobile_order')
                ->whereIn('order_id', $orderIds)
                ->where('user_id', 0)
                ->update([
                    'user_id' => $userId,
                ]);
        }

        if ($userId) {
            $where[] = ['user_id', '=', $userId];
        } else {
            return success('操作成功', []);
        }

        $list = Db::name('mobile_order')
            ->field('id, sub_order_id, mobile, amount, sale_price,
            supplier_status, created_at, refund_status, order_type')
            ->where($where)
            ->order('id desc')
            ->paginate([
                'page' => input('page', 1),
                'list_rows' => input('list_rows', 10),
            ])->toArray();

        return success('操作成功', $list);
    }

    /**
     * 手机号码查询.
     */
    public function phoneInfo()
    {
        return fail('此页面已下架，请登录后台获取新页面链接');

        $mobile = input('post.mobile');
        if (empty($mobile)) {
            return fail('请输入手机号码');
        }
        if (!checkMobile($mobile)) {
            return fail('手机号码格式有误');
        }

        $key = 'mobile_isp_cache_' . $mobile;
        $val = cache($key);
        if ($val) {
            return success('操作成功', $val);
        }

        $api = Db::name('mobile_supplier')
            ->where('code', 'quanmama')
            ->where('is_deleted', 0)
            ->find();
        if (empty($api)) {
            return success('');
        }
        $model = new \api\Quanmama($api);
        $info = $model->phoneInfo($mobile);
        $data = $info['data'] ?? [];
        if ($data) {
            cache($key, $data, 300);
        }

        return success('操作成功', $data);
    }

    /**
     * 获取客服链接.
     */
    public function getCustomerServiceUrl()
    {
        $url = Db::name('agent_config')
            ->where('agent_id', $this->agentChannel['agent_id'])
            ->value('customer_service_url');

        return success('操作成功', [
            'url' => $url,
        ]);
    }
}
